package cn.anecansaitin.whimsy.common.extension.comboSystem.skills.rockSceptre;

import cn.anecansaitin.whimsy.common.capabilities.IManaStorage;
import cn.anecansaitin.whimsy.common.capabilities.RockScepterManaStorage;
import cn.anecansaitin.whimsy.common.entity.DioriteMissile;
import cn.anecansaitin.whimsy.common.extension.comboSystem.ExtraData;
import cn.anecansaitin.whimsy.common.extension.comboSystem.IChargeableSkill;
import cn.anecansaitin.whimsy.common.item.RockSceptre;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import software.bernie.geckolib.animatable.GeoItem;

import java.util.Optional;

public class Attack4 implements IChargeableSkill {
    @Override
    public int precastTick() {
        return 0;
    }

    @Override
    public int maxChargingTick() {
        return 60 * 20;
    }

    @Override
    public int backswingTick() {
        return 10;
    }

    @Override
    public void prePrecast(Player player, ExtraData extra) {

    }

    @Override
    public void precast(int skillTick, Player player, ExtraData extra) {

    }

    @Override
    public void preCharging(Player player, ExtraData extra) {
        if (!player.level().isClientSide) {
            extra.getData("itemStack", ItemStack.class).ifPresent((i) -> {
                RockSceptre item = (RockSceptre) i.getItem();
                item.triggerAnim(player, GeoItem.getOrAssignId(i, (ServerLevel) player.level()), "con", "attack4.charging");
                item.triggerAnim(player, GeoItem.getOrAssignId(i, (ServerLevel) player.level()), "stone", "charging");
            });

            extra.putData("count", 0);
        }
    }

    @Override
    public void charging(int skillTick, Player player, ExtraData extra) {
        if (!player.level().isClientSide) {
            extra.getData("count", Integer.class).ifPresent(c -> {
                extra.putData("count", ++c);
                Optional<ItemStack> itemStackOptional = extra.getData("itemStack", ItemStack.class);

                if (itemStackOptional.isEmpty()) {
                    return;
                }

                ItemStack itemStack = itemStackOptional.get();
                RockSceptre item = (RockSceptre)itemStack.getItem();
                IManaStorage manaStorage = itemStack.getCapability(IManaStorage.MANA_STORAGE);

                if (manaStorage == null) {
                    return;
                }

                if (c == 10 && manaStorage.getManaStored(RockScepterManaStorage.DIORITE_TYPE) >= 30) {
                    extra.putData("missile", (byte) 0);
                    manaStorage.extractMana(RockScepterManaStorage.DIORITE_TYPE, 30, false);
                    item.triggerAnim(player, GeoItem.getOrAssignId(itemStack, (ServerLevel) player.level()), "part0", "show");
                } else if (c == 20 && manaStorage.getManaStored(RockScepterManaStorage.DIORITE_TYPE) >= 4 && extra.getData("missile", Byte.class).orElse((byte)-1) == 0) {
                    extra.putData("missile", (byte) 1);
                    manaStorage.extractMana(RockScepterManaStorage.DIORITE_TYPE, 4, false);
                    item.triggerAnim(player, GeoItem.getOrAssignId(itemStack, (ServerLevel) player.level()), "part1", "show");
                } else if (c == 30 && manaStorage.getManaStored(RockScepterManaStorage.DIORITE_TYPE) >= 4 && extra.getData("missile", Byte.class).orElse((byte)-1) == 1) {
                    extra.putData("missile", (byte) 2);
                    manaStorage.extractMana(RockScepterManaStorage.DIORITE_TYPE, 4, false);
                    item.triggerAnim(player, GeoItem.getOrAssignId(itemStack, (ServerLevel) player.level()), "part2", "show");
                } else if (c == 40 && manaStorage.getManaStored(RockScepterManaStorage.DIORITE_TYPE) >= 4 && extra.getData("missile", Byte.class).orElse((byte)-1) == 2) {
                    extra.putData("missile", (byte) 3);
                    manaStorage.extractMana(RockScepterManaStorage.DIORITE_TYPE, 4, false);
                    item.triggerAnim(player, GeoItem.getOrAssignId(itemStack, (ServerLevel) player.level()), "part3", "show");
                } else if (c == 50 && manaStorage.getManaStored(RockScepterManaStorage.DIORITE_TYPE) >= 4 && extra.getData("missile", Byte.class).orElse((byte)-1) == 3) {
                    extra.putData("missile", (byte) 4);
                    manaStorage.extractMana(RockScepterManaStorage.DIORITE_TYPE, 4, false);
                    item.triggerAnim(player, GeoItem.getOrAssignId(itemStack, (ServerLevel) player.level()), "part4", "show");
                    player.level().playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.EXPERIENCE_ORB_PICKUP, player.getSoundSource(), 0.5f, 0.1F);
                }
            });
        }
    }

    @Override
    public void preBackswing(Player player, ExtraData extra) {
        if (!player.level().isClientSide) {
            extra.putData("end", new Object());
            extra.getData("itemStack", ItemStack.class).ifPresent((i) -> {
                RockSceptre item = (RockSceptre) i.getItem();
                item.triggerAnim(player, GeoItem.getOrAssignId(i, (ServerLevel) player.level()), "con", "attack4.backswing");
                item.triggerAnim(player, GeoItem.getOrAssignId(i, (ServerLevel) player.level()), "part0", "hide");
                item.triggerAnim(player, GeoItem.getOrAssignId(i, (ServerLevel) player.level()), "part1", "hide");
                item.triggerAnim(player, GeoItem.getOrAssignId(i, (ServerLevel) player.level()), "part2", "hide");
                item.triggerAnim(player, GeoItem.getOrAssignId(i, (ServerLevel) player.level()), "part3", "hide");
                item.triggerAnim(player, GeoItem.getOrAssignId(i, (ServerLevel) player.level()), "part4", "hide");
                item.triggerAnim(player, GeoItem.getOrAssignId(i, (ServerLevel) player.level()), "stone", "idle");
            });

            extra.getData("missile", Byte.class).ifPresent(i -> {
                DioriteMissile missile = new DioriteMissile(player.level(), player, (byte) (i + 1));
                missile.shootFromRotation(player, player.getXRot(), player.getYRot(), 0, 2, 0);
                player.level().addFreshEntity(missile);
                player.level().playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.EVOKER_CAST_SPELL, player.getSoundSource(), 1, 1 + player.getRandom().nextFloat());
            });
        }
    }

    @Override
    public void backswing(int skillTick, Player player, ExtraData extra) {

    }

    @Override
    public boolean canCachingKey(int skillTick, ExtraData extra) {
        return extra.getData("end", Object.class).isEmpty();
    }

    @Override
    public boolean canDeriving(int skillTick, ExtraData extra) {
        int i = skillTick - getChargedTick(extra);
        return i >= 0 && i <= backswingTick();
    }

    @Override
    public void finish(Player player, ExtraData extra) {
        IChargeableSkill.super.finish(player, extra);
        extra.removeData("end");
        extra.removeData("missile");
    }

    @Override
    public String getName() {
        return "attack4";
    }
}
